#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "http/http.h"

const char *M_GET="GET";
const char *M_POST="POST";

const char *CONN_TYPE_CLOSE="Close";

struct robot_context* http_robot_context_build(){
	size_t size=sizeof(struct robot_context);
	struct robot_context *context=(struct robot_context*)malloc(size);
	if(context ==NULL){return NULL;}
	context->factory=bufferFactory_build(10240,2);
	return context;
	
}

int http_robot_context_release(struct robot_context *context){
	
	bufferFactory_release(context->factory);
	free(context);
	return 0;
}
int http_request_head(struct robot_context *context,struct buffer **request,const char *method,char *url,char *accept_type,char *ip, int port,const char *conn_life, char *body){
	struct bufferFactory *factory=context->factory;
	struct buffer *buff=buffer_new(factory);
	(*request)=buff;
    if(body)
        sprintf((*request)->data, "%s %s HTTP/1.1\r\nAccept: %s\r\nHost: %s:%d\r\nConnection: %s\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s\0", method, url,accept_type, ip, port, conn_life, strlen(body),body );
    else
        sprintf((*request)->data, "%s %s HTTP/1.1\r\nAccept: %s\r\nHost: %s:%d\r\nConnection: %s\r\n\r\n\0", method, url, accept_type, ip, port, conn_life);
	return 0;
}

int http_addr_reset(struct sockaddr_in *addr,char *host,int port){
	bzero(addr, sizeof(struct sockaddr_in));
    addr->sin_family = AF_INET;
    addr->sin_port = htons(port);
    inet_pton(AF_INET,host, &((addr->sin_addr).s_addr));
    return 0;
}


int http_fetch(struct robot_context *context,struct buffer *request,struct sockaddr_in *addr,struct buffer **response){
	
	int sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(sockfd < 0) {
		printf("create socket error!!! flag = %d\n", sockfd);
        exit(1);
    }
	int flag = connect(sockfd, (struct sockaddr *)addr, sizeof(*addr)); //建立和HTTP服务器的TCP链接
    if(flag < 0) {
        printf("connect error!!! flag = %d\n", flag);
        exit(1);
    }
	
	int wr_len=strlen(request->data);
	int sent=0;
	int offset=0;
	while(wr_len){
		sent = write(sockfd, (request->data)+offset, wr_len);
		offset +=sent;
		wr_len -=sent;
	}
    
	
	struct buffer *_response=buffer_new(context->factory);
	int length;

	int buff_len=_response->length;
        do {
        	length = read(sockfd, (_response->data)+_response->index, buff_len);
			
			printf("read %d \n",length);
			
            _response->index +=length;
			buff_len -=length;
			if(!buff_len){break;} 	
                /**write(1, _response, length);//如果是响应头部就打印至屏幕 **/
			if(!length)//注意，因为之前采用的是close方法，也就是说一旦传输数据完毕，则服务器端会断开链接，则read函数会返回0，所以这里会退出循环。如果采用的是Keep-Alive则服务器不关闭TCP链接，也就说程序将会被阻塞在read函数中，因此要注意的是自己判断是否读到了响应的结尾，然后在再次调用read之前退出循环。
				break;
        } while(1);
	*((_response->data)+_response->index)='\0';
	(*response)=_response;
	return 0;
}
 
/*
之前的头部比较简单，在发送请求的时候，我们常常会递交表单，如果采用GET方法，则可以通过URL传递参数。如果采用POST，则新的HTTP请求看上去应该是这样。（带COOKIE）

 

POST http://192.168.1.154:8888/httpstudy2/servlet/IndexServlet HTTP/1.1
Accept: html/text
Host: 192.168.1.154:8888

Cookie: username=difa; password=yuna
Connection: Close
Content-Type: application/x-www-form-urlencoded
Content-Length: 29

username=hello&password=world

 

Content-Type表示主体类型

Content-Length表示主体长度，不包括头部。

 

整个发送的HTTP请求应该是：

POST http://192.168.1.154:8888/httpstudy2/servlet/IndexServlet HTTP/1.1\r\n
Accept: html/text\r\n
Host: 192.168.1.154:8888\r\n
Cookie: username=difa; password=yuna\r\n
Connection: Close\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 29\r\n\
r\n
username=hello&password=world
*/
